﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LockDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                MyTask t = new MyTask();

                #region 同步的例子
                Console.WriteLine("同步的例子");
                t.DoSync();
                t.DoSync();
                Console.WriteLine();
                #endregion

                #region 异步的例子 -- 不加任何锁
                Console.WriteLine("异步的例子 -- 不加任何锁");
                t.MyList.Clear();
                Task t1 = Task.Factory.StartNew(() => t.DoParallelWithoutLock());
                Task t2 = Task.Factory.StartNew(() => t.DoParallelWithoutLock());
                Task.WaitAll(t1, t2);
                Console.WriteLine();
                #endregion

                #region 异步的例子 -- 使用 Lock (this) 方式
                Console.WriteLine("使用 Lock (this) 方式");
                t.MyList.Clear();
                Task t3 = Task.Factory.StartNew(() => t.DoParallelByLockThis());
                Task t4 = Task.Factory.StartNew(() => t.DoParallelByLockThis());
                Task.WaitAll(t3, t4);
                Console.WriteLine();
                #endregion

                #region 异步的例子 -- 使用 Lock (this) 方式 -- 死锁
                Console.WriteLine("使用 Lock (this) 方式 -- 死锁");
                t.MyList.Clear();
                Task t5 = Task.Factory.StartNew(() => t.DoParallelByLockThis());
                Task t6 = Task.Factory.StartNew(() => t.DoParallelByLockThis());
                lock (t)
                {
                    Console.WriteLine("模拟死锁开始，在其它地方调用了lock(同一个实例)");
                    Thread.Sleep(3000);
                    Console.WriteLine("死锁结束");
                }
                Task.WaitAll(t5, t6);
                Console.WriteLine();
                #endregion

                #region 异步的例子 -- 使用 Lock (string) 方式 -- 死锁
                Console.WriteLine("使用 Lock (string) 方式 -- 死锁");
                t.MyList.Clear();
                Task t7 = Task.Factory.StartNew(() => t.DoParallelByLockString());
                Task t8 = Task.Factory.StartNew(() => t.DoParallelByLockString());
                lock ("aa")
                {
                    Console.WriteLine("模拟死锁开始，在其它地方调用了lock(同一个字符串)");
                    Thread.Sleep(3000);
                    Console.WriteLine("死锁结束");
                }
                Task.WaitAll(t7, t8);
                Console.WriteLine();
                #endregion


                #region 异步的例子 -- 使用 Lock (方法内变量) 方式
                Console.WriteLine("使用 Lock (方法内变量) 方式 ");
                t.MyList.Clear();
                Task t9 = Task.Factory.StartNew(() => t.DoParallelByLockMethodLevelFiled());
                Task t10 = Task.Factory.StartNew(() => t.DoParallelByLockMethodLevelFiled());
                Task.WaitAll(t9, t10);
                Console.WriteLine();
                #endregion

                #region 异步的例子 -- 正确做法
                Console.WriteLine("异步的例子 -- 正确做法");
                t.MyList.Clear();
                Task t11 = Task.Factory.StartNew(() => t.DoParallelByLockCorrectly());
                Task t12 = Task.Factory.StartNew(() => t.DoParallelByLockCorrectly());
                lock (t)
                {
                    Console.WriteLine("模拟死锁开始，在其它地方调用了lock(同一个字符串)");
                    Thread.Sleep(3000);
                    Console.WriteLine("死锁结束");
                }
                Task.WaitAll(t11, t12);
                Console.WriteLine();
                #endregion


                if (ConsoleKey.Escape == Console.ReadKey().Key)
                {
                    break;
                }
            }
        }
    }
}
